#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'James Iter'
__date__ = '15/12/16'
__contact__ = 'james.iter.cn@gmail.com'
__copyright__ = '(c) 2015 by James Iter.'

import copy

import jimit as ji
from enum import Enum

import states


class Rules(Enum):
    CYCLE_UNIT = (basestring, 'cycle_unit', ['d', 'w', 'm'])
    OFFSET = ((int, long), 'offset')
    TIMESTAMP = ((int, long), 'timestamp', (0, 9223372036854775807))
    DOMAIN = (int, 'domain', states.DBDomain.__members__.values())
    RW_MODE = (int, 'rw_mode', states.RWMode.__members__.values())
    PORT = ((int, long), 'port', (1, 65535), False)
    DB_HOST = (basestring, 'host', (1, 64))
    DB_USER = (basestring, 'user', (1, 64))
    DB_PASSWORD = (basestring, 'password', (1, 64))
    DB_DATABASE = (basestring, 'database', (1, 64))
    DB_POOL_SIZE = ((int, long), 'pool_size', (1, 32))
    # 合理的年份
    DB_SEQUENCE_FLAG = ((int, long), 'sequence_flag', (2000, 3000))
    JSON = (dict, 'json')
    # dsl字符串长度范围
    DSL = (basestring, 'dsl', (8, 1000))
    # dsl解析后的元素数量
    DSL_ELEMENT_S = (list, 'ele_s', (3, 3))

    TINYINT = [(int, long), 'replace', (-128, 127)]
    U_TINYINT = [(int, long), 'replace', (0, 255)]
    SMALLINT = [(int, long), 'replace', (-32768, 32767)]
    U_SMALLINT = [(int, long), 'replace', (0, 65535)]
    MEDIUMINT = [(int, long), 'replace', (-8388608, -8388608)]
    U_MEDIUMINT = [(int, long), 'replace', (0, 16777215)]
    INT = [(int, long), 'replace', (-2147483648, 2147483647)]
    U_INT = [(int, long), 'replace', (0, 4294967295)]
    BIGINT = [(int, long), 'replace', (-9223372036854775808, 9223372036854775807)]
    U_BIGINT = [(int, long), 'replace', (0, 18446744073709551615)]
    CHAR = [basestring, 'replace', [0, 255]]
    VARCHAR = [basestring, 'replace', [0, 65535]]
    ENUM = [basestring, 'replace', []]
    TEXT = [basestring, 'replace', [0, 65535]]

    DB_FIELD = (basestring, 'field', (1, 64))
    DB_DATA_TYPE = (basestring, 'data_type', ['TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT', 'CHAR', 'VARCHAR',
                                              'ENUM', 'TEXT'])
    DB_LENGTH = ((int, long), 'char_length', (0, 65535))

    @staticmethod
    def get_db_field_rule(field=None, data_type=None, column_type=None, char_length=None, is_nullable=False):
        args_rules = [
            Rules.DB_FIELD.value,
            Rules.DB_DATA_TYPE.value,
            Rules.DB_LENGTH.value,
            (basestring, 'column_type')
        ]
        ji.Check.previewing(args_rules, locals())

        if data_type in ['TINYINT', 'SMALLINT', 'MEDIUMINT', 'INT', 'BIGINT']:
            if column_type.find('unsigned') != -1:
                rule = copy.deepcopy(eval(''.join(['Rules.U_', data_type, '.value'])))
            else:
                rule = copy.deepcopy(eval(''.join(['Rules.', data_type, '.value'])))

        elif data_type in ['CHAR', 'VARCHAR', 'TEXT']:
            rule = copy.deepcopy(eval(''.join(['Rules.', data_type, '.value'])))
            # 检测传入的length参数是否超出合理值范围
            args_rules = [
                ((int, long), data_type, tuple(rule[2]))
            ]
            ji.Check.previewing(args_rules, {data_type: char_length})
            rule[2][1] = char_length
            rule[2] = tuple(rule[2])

        elif data_type == 'ENUM':
            rule = copy.deepcopy(eval(''.join(['Rules.', data_type, '.value'])))
            enum_members = column_type.lstrip('enum(').rstrip(')').replace('\'', '').split(',')
            if isinstance(enum_members[0], basestring):
                rule[0] = basestring
            elif isinstance(enum_members[0], (int, long)):
                rule[0] = (int, long)
            else:
                return

            rule[2] = enum_members

        else:
            return

        rule[1] = field
        if is_nullable:
            # rule第4个参数为,是否为必须字段,如果可以为空,表示该字段为非必须字段,所以这里传入False
            rule.append(False)

        return tuple(rule)
